/**
	This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
package br.biofoco.p2p.bulk;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * Read a FASTA file with many sequences and create a file for each sequence.
 * This way of processing FASTA files is OUT-OF-DATE according with our new approach.
 * 
 * @author Victor, Gustavo and Edward (refactoring)
 */

public class FastaParser {

	private int numSeqs;			  // numero de sequencias
	private int fileIndex;			  // indice do proximo arquivo a ser retornado
	private List<File> fileList;	  // lista dos arquivos criados
	
	/**
	 * Construtor
	 * 
	 */
	public FastaParser() {	
		numSeqs = 0;
		fileIndex = 0;
		fileList = Collections.synchronizedList(new ArrayList<File>());
	}
		
	/**
	 * Parse the content of the FASTA file and generate a file for each conting in the file. 
     * @param inPath absolute input path of the FASTA file
     * @param outPath path where each contig will be recorded
	 * @param filename name of the FASTA file with many sequences 
	 */
	public List<File> parse(String inPath, File outDir) throws IOException {
		
		File file;		// arquivo com somente uma sequencia, que sera criado
		StringBuilder seqName = new StringBuilder(); // nome da sequencia atual		
		BufferedReader breader = new BufferedReader(new FileReader(inPath));
		BufferedWriter bwriter = null;
				
		int c;
		while ((c = breader.read()) != -1) {
			if (c == '>') {
				// se este nao eh o primeiro contig
				if (bwriter != null) {
					bwriter.close();
				}
					
				// Le o nome da sequencia (ate encontrar espaco, tab ou nova
				// linha), que sera o nome do arquivo que contem somente
				// uma sequencia
				c = breader.read();
				// ignora os espacos depois de '>'
				while (c == ' ' || c == '\t') {
					c = breader.read();
				}

				while (c != ' ' && c != '\t' && c != '\n') {
					seqName.append((char)c);
					c = breader.read();
				}
					
				// criacao de um arquivo com somente uma sequencia
				// adiciona o arquivo aa lista de arquivos criados
				// escreve '> nome_sequencia ' no arquivo e zera o
				// StringBuilder
				//nomeArquivoComUmaSequencia = new String(seqName);
				file = new File(outDir, seqName.toString().trim());
				
				fileList.add(file);
				bwriter = new BufferedWriter(new FileWriter(file));
					
				numSeqs++;
				bwriter.write('>');
				bwriter.write(seqName.toString()+(char)c);
				seqName = new StringBuilder();
			}  else {
				bwriter.write(c);
			} // END-IF-ELSE
		} // END-WHILE
	   breader.close();
	   bwriter.close();
	   return fileList;
	}
	
	/**
	 * Retorna o numero de sequencias contidas no arquivo passado ao construtor 
	 * @return numero de sequencias 
	 */
	public int getNumSeqs() {
		return numSeqs;
	}
	
	/**
	 * Indica se ainda ha arquivos, dentre aqueles que foram criados pelo 
	 * construtor
	 * @return true caso ainda existam arquivos e false caso contrario
	 */
	public boolean hasMoreFiles() {
		if (fileIndex < numSeqs)
			return true;
		else
			return false;
	}
	
	/**
	 * Retorna o arquivo cujo indice eh fileIndex, isto eh, o primeiro arquivo
	 * criado que ainda nao foi retornado 
	 * @return objeto File do proximo arquivo, ou null caso nao haja mais 
	 * arquivos
	 */
	public File getNextFile() {
		if (fileIndex < numSeqs) {
			fileIndex++;
			return fileList.get(fileIndex-1);
		} else {
			return null;
		}
	}
	
	/**
	 * Volta o indice da lista de arquivos para o inicio.
	 */
	public void resetIndex() {
		fileIndex = 0;
	}
}
